package com.zzg.mybatis.generator.controller;

import com.zzg.mybatis.generator.model.ColumnEntity;
import com.zzg.mybatis.generator.model.DatabaseConfig;
import com.zzg.mybatis.generator.model.GeneratorConfig;
import com.zzg.mybatis.generator.model.ItemInfo;
import com.zzg.mybatis.generator.model.TableEntity;
import com.zzg.mybatis.generator.model.UITableColumnVO;
import com.zzg.mybatis.generator.util.ConfigHelper;
import com.zzg.mybatis.generator.util.DbUtil;
import com.zzg.mybatis.generator.util.GenUtils;
import com.zzg.mybatis.generator.util.MyStringUtils;
import com.zzg.mybatis.generator.view.AlertUtil;

import cn.hutool.core.util.StrUtil;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.TextFieldTreeCell;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.stage.DirectoryChooser;
import javafx.util.Callback;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.awt.*;
import java.io.File;
import java.net.URL;
import java.sql.SQLRecoverableException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.ResourceBundle;
import java.util.stream.Collectors;

public class MainUIController extends BaseFXController {

    private static final Logger _LOG = LoggerFactory.getLogger(MainUIController.class);
    private static final String FOLDER_NO_EXIST = "部分目录不存在，是否创建";

    /**	上部-导航菜单 **/
    @FXML
    private Label connectionLabel;
    @FXML
    private Label configsLabel;
    
    /**	左侧-DB树列表 **/
    @FXML
    private TreeView<String> leftDBTree;
    
    @FXML
    private TextField tableNameField;
    @FXML
    private TextField domainObjectNameField;
    @FXML
    private TextField projectFolderField;

    private DatabaseConfig selectedDatabaseConfig;
    private String tableName;
    
    /** 版本v0.0.1 开始 **/
    @FXML
    private TextField dom;
    @FXML
    private TextField provider;
    @FXML
    private TextField mapper;
    @FXML
    private TextField dto;
    @FXML
    private TextField converter;
    @FXML
    private TextField service;
    @FXML
    private TextField serviceImpl;
    @FXML
    private TextField requestSave;
    @FXML
    private TextField requestUpdate;
    @FXML
    private TextField requestSort;
    @FXML
    private TextField response;
    @FXML
    private TextField exception;
    @FXML
    private TextField controller;

    
    @FXML
    private TextField domPackage;
    @FXML
    private TextField providerPackage;
    @FXML
    private TextField mapperPackage;
    @FXML
    private TextField dtoPackage;
    @FXML
    private TextField converterPackage;
    @FXML
    private TextField servicePackage;
    @FXML
    private TextField serviceImplPackage;
    @FXML
    private TextField requestSavePackage;
    @FXML
    private TextField requestUpdatePackage;
    @FXML
    private TextField requestSortPackage;
    @FXML
    private TextField responsePackage;
    @FXML
    private TextField exceptionPackage;
    @FXML
    private TextField controllerPackage;
    
    @FXML
    private TextField domTargetProject;
    @FXML
    private TextField providerTargetProject;
    @FXML
    private TextField mapperTargetProject;
    @FXML
    private TextField dtoTargetProject;
    @FXML
    private TextField converterTargetProject;
    @FXML
    private TextField serviceTargetProject;
    @FXML
    private TextField serviceImplTargetProject;
    @FXML
    private TextField requestSaveTargetProject;
    @FXML
    private TextField requestUpdateTargetProject;
    @FXML
    private TextField requestSortTargetProject;
    @FXML
    private TextField responseTargetProject;
    @FXML
    private TextField exceptionTargetProject;
    @FXML
    private TextField controllerTargetProject;
    
    @FXML
    private TextField tb;
    @FXML
    private TextField SQLUtilPackage;
    @FXML
    private TextField cv;
    @FXML
    private TextField ep;
    @FXML
    private TextField ct;
    @FXML
    private TextField rp;
    @FXML
    private TextField apisort;
    @FXML
    private CheckBox isremoveprefix;
    
    private List<ColumnEntity> ceEqualList;
    private List<ColumnEntity> ceInList;
    private List<ColumnEntity> ceLikeList;
    private List<ColumnEntity> ceAllList;
    /** 版本v1.0.0 结束 **/
    
    
	@SuppressWarnings("unchecked")
	@Override
    public void initialize(URL location, ResourceBundle resources) {
        ImageView dbImage = new ImageView("icons/computer.png");
        dbImage.setFitHeight(40);
        dbImage.setFitWidth(40);
        connectionLabel.setGraphic(dbImage);
        connectionLabel.setOnMouseClicked(event -> {
            DbConnectionController controller = (DbConnectionController) loadFXMLPage("新建数据库连接", FXMLPage.NEW_CONNECTION, false);
            controller.setMainUIController(this);
            controller.showDialogStage();
        });
        ImageView configImage = new ImageView("icons/config-list.png");
        configImage.setFitHeight(40);
        configImage.setFitWidth(40);
        configsLabel.setGraphic(configImage);
        configsLabel.setOnMouseClicked(event -> {
            GeneratorConfigController controller = (GeneratorConfigController) loadFXMLPage("配置", FXMLPage.GENERATOR_CONFIG, false);
            controller.setMainUIController(this);
            controller.showDialogStage();
        });

        leftDBTree.setShowRoot(false);
        leftDBTree.setRoot(new TreeItem<>());
        Callback<TreeView<String>, TreeCell<String>> defaultCellFactory = TextFieldTreeCell.forTreeView();
        leftDBTree.setCellFactory((TreeView<String> tv) -> {
            TreeCell<String> cell = defaultCellFactory.call(tv);
            cell.addEventHandler(MouseEvent.MOUSE_CLICKED, event -> {
                int level = leftDBTree.getTreeItemLevel(cell.getTreeItem());
                TreeCell<String> treeCell = (TreeCell<String>) event.getSource();
                TreeItem<String> treeItem = treeCell.getTreeItem();
                if (level == 1) {
                    final ContextMenu contextMenu = new ContextMenu();
                    MenuItem item1 = new MenuItem("关闭连接");
                    item1.setOnAction(event1 -> treeItem.getChildren().clear());
	                MenuItem item2 = new MenuItem("编辑连接");
	                item2.setOnAction(event1 -> {
		                DatabaseConfig selectedConfig = (DatabaseConfig) treeItem.getGraphic().getUserData();
		                DbConnectionController controller = (DbConnectionController) loadFXMLPage("编辑数据库连接", FXMLPage.NEW_CONNECTION, false);
		                controller.setMainUIController(this);
		                controller.setConfig(selectedConfig);
		                controller.showDialogStage();
	                });
                    MenuItem item3 = new MenuItem("删除连接");
                    item3.setOnAction(event1 -> {
                        DatabaseConfig selectedConfig = (DatabaseConfig) treeItem.getGraphic().getUserData();
                        try {
                            ConfigHelper.deleteDatabaseConfig(selectedConfig);
                            this.loadLeftDBTree();
                        } catch (Exception e) {
                            AlertUtil.showErrorAlert("Delete connection failed! Reason: " + e.getMessage());
                        }
                    });
                    contextMenu.getItems().addAll(item1, item2, item3);
                    cell.setContextMenu(contextMenu);
                }
                if (event.getClickCount() == 2) {
                    if(treeItem == null) {
                        return ;
                    }
                    treeItem.setExpanded(true);
                    if (level == 1) {
                        System.out.println("index: " + leftDBTree.getSelectionModel().getSelectedIndex());
                        DatabaseConfig selectedConfig = (DatabaseConfig) treeItem.getGraphic().getUserData();
                        try {
                            List<String> tables = DbUtil.getTableNames(selectedConfig);
                            if (tables != null && tables.size() > 0) {
                                ObservableList<TreeItem<String>> children = cell.getTreeItem().getChildren();
                                children.clear();
                                for (String tableName : tables) {
                                    TreeItem<String> newTreeItem = new TreeItem<>();
                                    ImageView imageView = new ImageView("icons/table.png");
                                    imageView.setFitHeight(16);
                                    imageView.setFitWidth(16);
                                    newTreeItem.setGraphic(imageView);
                                    newTreeItem.setValue(tableName);
                                    children.add(newTreeItem);
                                }
                            }
                        } catch (SQLRecoverableException e) {
                            _LOG.error(e.getMessage(), e);
                            AlertUtil.showErrorAlert("连接超时");
                        } catch (Exception e) {
                            _LOG.error(e.getMessage(), e);
                            AlertUtil.showErrorAlert(e.getMessage());
                        }
                    } else if (level == 2) { // left DB tree level3
                        String tableName = treeCell.getTreeItem().getValue();
                        this.tableName = tableName;
                        
                        if(isremoveprefix.isSelected()) {
                        	tableName = StrUtil.subAfter(tableName, "_", false);
                        }
                        
                        selectedDatabaseConfig = (DatabaseConfig) treeItem.getParent().getGraphic().getUserData();
                       
                        tableNameField.setText(treeCell.getTreeItem().getValue());
                        domainObjectNameField.setText(MyStringUtils.dbStringToCamelStyle(tableName));
                        
                        dom.setText(domainObjectNameField.getText().concat("DO"));
                        provider.setText(domainObjectNameField.getText().concat("DAOProvider"));
                        mapper.setText(domainObjectNameField.getText().concat("Mapper"));
                        dto.setText(domainObjectNameField.getText().concat("DTO"));
                        
                        converter.setText(domainObjectNameField.getText().concat("Converter"));
                        service.setText(domainObjectNameField.getText().concat("Service"));
                        serviceImpl.setText(domainObjectNameField.getText().concat("ServiceImpl"));
                        requestSave.setText(domainObjectNameField.getText().concat("SaveRequest"));
                        requestUpdate.setText(domainObjectNameField.getText().concat("UpdateRequest"));
                        
                        response.setText(domainObjectNameField.getText().concat("Response"));
                        exception.setText(domainObjectNameField.getText().concat("ExceptionCode"));
                        controller.setText(domainObjectNameField.getText().concat("Controller"));
                        
                    }
                }
            });
            return cell;
        });
        loadLeftDBTree();
		setTooltip();
		//默认选中第一个，否则如果忘记选择，没有对应错误提示
        //encodingChoice.getSelectionModel().selectFirst();
	}

	private void setTooltip() {
		//encodingChoice.setTooltip(new Tooltip("生成文件的编码，必选"));
		//generateKeysField.setTooltip(new Tooltip("insert时可以返回主键ID"));
		//offsetLimitCheckBox.setTooltip(new Tooltip("是否要生成分页查询代码"));
		//commentCheckBox.setTooltip(new Tooltip("使用数据库的列注释作为实体类字段名的Java注释 "));
		//useActualColumnNamesCheckbox.setTooltip(new Tooltip("是否使用数据库实际的列名作为实体类域的名称"));
		//useTableNameAliasCheckbox.setTooltip(new Tooltip("在Mapper XML文件中表名使用别名，并且列全部使用as查询"));
		//overrideXML.setTooltip(new Tooltip("重新生成时把原XML文件覆盖，否则是追加"));
        //useDAOExtendStyle.setTooltip(new Tooltip("将通用接口方法放在公共接口中，DAO接口留空"));
        //forUpdateCheckBox.setTooltip(new Tooltip("在Select语句中增加for update后缀"));
	}

	void loadLeftDBTree() {
        TreeItem<String> rootTreeItem = leftDBTree.getRoot();
        rootTreeItem.getChildren().clear();
        try {
            List<DatabaseConfig> dbConfigs = ConfigHelper.loadDatabaseConfig();
            for (DatabaseConfig dbConfig : dbConfigs) {
                TreeItem<String> treeItem = new TreeItem<>();
                treeItem.setValue(dbConfig.getName());
                ImageView dbImage = new ImageView("icons/computer.png");
                dbImage.setFitHeight(16);
                dbImage.setFitWidth(16);
                dbImage.setUserData(dbConfig);
                treeItem.setGraphic(dbImage);
                rootTreeItem.getChildren().add(treeItem);
            }
        } catch (Exception e) {
            _LOG.error("connect db failed, reason: {}", e);
            AlertUtil.showErrorAlert(e.getMessage() + "\n" + ExceptionUtils.getStackTrace(e));
        }
    }

    @FXML
    public void chooseProjectFolder() {
        DirectoryChooser directoryChooser = new DirectoryChooser();
        File selectedFolder = directoryChooser.showDialog(getPrimaryStage());
        if (selectedFolder != null) {
            projectFolderField.setText(selectedFolder.getAbsolutePath());
        }
    }

    @FXML
    public void generateCode2() {
        if (tableName == null) { AlertUtil.showWarnAlert("请先在左侧选择数据库表"); return; }
        String result = validateConfig();
		if (result != null) { AlertUtil.showErrorAlert(result); return; }
        GeneratorConfig generatorConfig = getGeneratorConfigFromUI();
        if (!checkDirs(generatorConfig)) { return; }
        
        this.setItem(generatorConfig);
		
        try {
        	List<TableEntity> table = DbUtil.getTable(selectedDatabaseConfig, tableName);
        	List<ColumnEntity> columns = DbUtil.getColumns(selectedDatabaseConfig, tableName);
            
        	// 过滤前缀
        	if(isremoveprefix.isSelected() && CollectionUtils.isNotEmpty(table)) {
        		for(TableEntity tb : table) {
        			tb.setTableName(StrUtil.subAfter(tb.getTableName(), "_", false));
        		}
        	}
        	
        	GenUtils.generatorCode(table.get(0), "moduleName", "packageName", "", columns, generatorConfig,
        			this.getCeEqualList(), this.getCeInList(), this.getCeLikeList(), this.getCeAllList());
        	
        	AlertUtil.showInfoAlert("恭喜!代码已生成！");
        } catch (Exception e) {
            _LOG.error(e.getMessage(), e);
            AlertUtil.showErrorAlert(e.getMessage());
        }
        
    }
    

	private void setItem(GeneratorConfig grc) {
		ItemInfo itemInfoDO = new ItemInfo("DO", grc.getDom(), grc.getDomPackage(), grc.getDomTargetProject());
		ItemInfo itemInfoProvider = new ItemInfo("Provider", grc.getProvider(), grc.getProviderPackage(), grc.getProviderTargetProject());
		ItemInfo itemInfoMapper = new ItemInfo("Mapper", grc.getMapper(), grc.getMapperPackage(), grc.getMapperTargetProject());
		ItemInfo itemInfoDto = new ItemInfo("Dto", grc.getDto(), grc.getDtoPackage(), grc.getDtoTargetProject());
		ItemInfo itemInfoConverter = new ItemInfo("Converter", grc.getConverter(), grc.getConverterPackage(), grc.getConverterTargetProject());
		ItemInfo itemInfoService = new ItemInfo("Service", grc.getService(), grc.getServicePackage(), grc.getServiceTargetProject());
		ItemInfo itemInfoServiceImpl = new ItemInfo("ServiceImpl", grc.getServiceImpl(), grc.getServiceImplPackage(), grc.getServiceImplTargetProject());
		ItemInfo itemInfoRequestSave = new ItemInfo("RequestSave", grc.getRequestSave(), grc.getRequestSavePackage(), grc.getRequestSaveTargetProject());
		ItemInfo itemInfoRequestUpdate = new ItemInfo("RequestUpdate", grc.getRequestUpdate(), grc.getRequestUpdatePackage(), grc.getRequestUpdateTargetProject());
		ItemInfo itemInfoResponse = new ItemInfo("Response", grc.getResponse(), grc.getResponsePackage(), grc.getResponseTargetProject());
		ItemInfo itemInfoException = new ItemInfo("Exception", grc.getException(), grc.getExceptionPackage(), grc.getExceptionTargetProject());
		ItemInfo itemInfoController = new ItemInfo("Controller", grc.getController(), grc.getControllerPackage(), grc.getControllerTargetProject());
		
		GenUtils.itemMap.put("DO", itemInfoDO);
		GenUtils.itemMap.put("Provider", itemInfoProvider);
		GenUtils.itemMap.put("Mapper", itemInfoMapper);
		GenUtils.itemMap.put("Dto", itemInfoDto);
		GenUtils.itemMap.put("Converter", itemInfoConverter);
		GenUtils.itemMap.put("Service", itemInfoService);
		GenUtils.itemMap.put("ServiceImpl", itemInfoServiceImpl);
		GenUtils.itemMap.put("RequestSave", itemInfoRequestSave);
		GenUtils.itemMap.put("RequestUpdate", itemInfoRequestUpdate);
		GenUtils.itemMap.put("Response", itemInfoResponse);
		GenUtils.itemMap.put("Exception", itemInfoException);
		GenUtils.itemMap.put("Controller", itemInfoController);
		
	}

	private String validateConfig() {
		String projectFolder = projectFolderField.getText();
		if (StringUtils.isEmpty(projectFolder))  {
			return "项目目录不能为空";
		}
		if (StringUtils.isEmpty(domainObjectNameField.getText()))  {
			return "类名不能为空";
		}
		if (StringUtils.isAnyEmpty(domTargetProject.getText(), 
				domTargetProject.getText(), domTargetProject.getText())) {
			return "包名不能为空";
		}

		return null;
	}

	@FXML
    public void saveGeneratorConfig() {
        TextInputDialog dialog = new TextInputDialog("");
        dialog.setTitle("保存当前配置");
        dialog.setContentText("请输入配置名称");
        Optional<String> result = dialog.showAndWait();
        if (result.isPresent()) {
            String name = result.get();
            if (StringUtils.isEmpty(name)) {
                AlertUtil.showErrorAlert("名称不能为空");
                return;
            }
            _LOG.info("user choose name: {}", name);
            try {
            	ConfigHelper.deleteGeneratorConfig(name);
            	GeneratorConfig generatorConfig = getGeneratorConfigFromUI();
            	generatorConfig.setName(name);
            	ConfigHelper.saveGeneratorConfig(generatorConfig);
            } catch (Exception e) {
                AlertUtil.showErrorAlert("删除配置失败");
            }
        }
    }

    public GeneratorConfig getGeneratorConfigFromUI() {
        GeneratorConfig generatorConfig = new GeneratorConfig();
        generatorConfig.setProjectFolder(projectFolderField.getText());
        generatorConfig.setTb(tb.getText());
        generatorConfig.setSQLUtilPackage(SQLUtilPackage.getText());
        generatorConfig.setCv(cv.getText());
        generatorConfig.setEp(ep.getText());
        generatorConfig.setCt(ct.getText());
        generatorConfig.setRp(rp.getText());
        generatorConfig.setApisort(apisort.getText());
        generatorConfig.setIsremoveprefix(isremoveprefix.isSelected());
        
        
        generatorConfig.setDom(dom.getText());
        generatorConfig.setProvider(provider.getText());
        generatorConfig.setMapper(mapper.getText());
        generatorConfig.setDto(dto.getText());
        generatorConfig.setConverter(converter.getText());
        generatorConfig.setService(service.getText());
        generatorConfig.setServiceImpl(serviceImpl.getText());
        generatorConfig.setRequestSave(requestSave.getText());
        generatorConfig.setRequestUpdate(requestUpdate.getText());
        generatorConfig.setResponse(response.getText());
        generatorConfig.setException(exception.getText());
        generatorConfig.setController(controller.getText());
        
        generatorConfig.setDomPackage(domPackage.getText());
        generatorConfig.setProviderPackage(providerPackage.getText());
        generatorConfig.setMapperPackage(mapperPackage.getText());
        generatorConfig.setDtoPackage(dtoPackage.getText());
        generatorConfig.setConverterPackage(converterPackage.getText());
        generatorConfig.setServicePackage(servicePackage.getText());
        generatorConfig.setServiceImplPackage(serviceImplPackage.getText());
        generatorConfig.setRequestSavePackage(requestSavePackage.getText());
        generatorConfig.setRequestUpdatePackage(requestUpdatePackage.getText());
        generatorConfig.setResponsePackage(responsePackage.getText());
        generatorConfig.setExceptionPackage(exceptionPackage.getText());
        generatorConfig.setControllerPackage(controllerPackage.getText());
        
        generatorConfig.setDomTargetProject(domTargetProject.getText());
        generatorConfig.setProviderTargetProject(providerTargetProject.getText());
        generatorConfig.setMapperTargetProject(mapperTargetProject.getText());
        generatorConfig.setDtoTargetProject(dtoTargetProject.getText());
        generatorConfig.setConverterTargetProject(converterTargetProject.getText());
        generatorConfig.setServiceTargetProject(serviceTargetProject.getText());
        generatorConfig.setServiceImplTargetProject(serviceImplTargetProject.getText());
        generatorConfig.setRequestSaveTargetProject(requestSaveTargetProject.getText());
        generatorConfig.setRequestUpdateTargetProject(requestUpdateTargetProject.getText());
        generatorConfig.setResponseTargetProject(responseTargetProject.getText());
        generatorConfig.setExceptionTargetProject(exceptionTargetProject.getText());
        generatorConfig.setControllerTargetProject(controllerTargetProject.getText());
        
        return generatorConfig;
    }

    public void setGeneratorConfigIntoUI(GeneratorConfig generatorConfig) {
    	projectFolderField.setText(generatorConfig.getProjectFolder());
    	tb.setText(generatorConfig.getTb());
    	SQLUtilPackage.setText(generatorConfig.getSQLUtilPackage());
    	cv.setText(generatorConfig.getCv());
    	ep.setText(generatorConfig.getEp());
    	ct.setText(generatorConfig.getCt());
    	rp.setText(generatorConfig.getRp());
    	apisort.setText(generatorConfig.getApisort());
    	isremoveprefix.setSelected(generatorConfig.isIsremoveprefix());
    	
    	dom.setText(generatorConfig.getDom());
        provider.setText(generatorConfig.getProvider());
        mapper.setText(generatorConfig.getMapper());
        dto.setText(generatorConfig.getDto());
        converter.setText(generatorConfig.getConverter());
        service.setText(generatorConfig.getService());
        serviceImpl.setText(generatorConfig.getServiceImpl());
        requestSave.setText(generatorConfig.getRequestSave());
        requestUpdate.setText(generatorConfig.getRequestUpdate());
        response.setText(generatorConfig.getResponse());
        exception.setText(generatorConfig.getException());
        controller.setText(generatorConfig.getController());
        
        domPackage.setText(generatorConfig.getDomPackage());
        providerPackage.setText(generatorConfig.getProviderPackage());
        mapperPackage.setText(generatorConfig.getMapperPackage());
        dtoPackage.setText(generatorConfig.getDtoPackage());
        converterPackage.setText(generatorConfig.getConverterPackage());
        servicePackage.setText(generatorConfig.getServicePackage());
        serviceImplPackage.setText(generatorConfig.getServiceImplPackage());
        requestSavePackage.setText(generatorConfig.getRequestSavePackage());
        requestUpdatePackage.setText(generatorConfig.getRequestUpdatePackage());
        responsePackage.setText(generatorConfig.getResponsePackage());
        exceptionPackage.setText(generatorConfig.getExceptionPackage());
        controllerPackage.setText(generatorConfig.getControllerPackage());
        
        domTargetProject.setText(generatorConfig.getDomTargetProject());
        providerTargetProject.setText(generatorConfig.getProviderTargetProject());
        mapperTargetProject.setText(generatorConfig.getMapperTargetProject());
        dtoTargetProject.setText(generatorConfig.getDtoTargetProject());
        converterTargetProject.setText(generatorConfig.getConverterTargetProject());
        serviceTargetProject.setText(generatorConfig.getServiceTargetProject());
        serviceImplTargetProject.setText(generatorConfig.getServiceImplTargetProject());
        requestSaveTargetProject.setText(generatorConfig.getRequestSaveTargetProject());
        requestUpdateTargetProject.setText(generatorConfig.getRequestUpdateTargetProject());
        responseTargetProject.setText(generatorConfig.getResponseTargetProject());
        exceptionTargetProject.setText(generatorConfig.getExceptionTargetProject());
        controllerTargetProject.setText(generatorConfig.getControllerTargetProject());
    }

    @FXML
    public void openTableColumnCustomizationPage() {
        if (tableName == null) {
            AlertUtil.showWarnAlert("请先在左侧选择数据库表");
            return;
        }
        SelectTableColumnController controller = (SelectTableColumnController) loadFXMLPage("定制列", FXMLPage.SELECT_TABLE_COLUMN, true);
        controller.setMainUIController(this);
        try {
            if (!tableName.equals(controller.getTableName())) {
                List<UITableColumnVO> tableColumns = DbUtil.getTableColumns(selectedDatabaseConfig, tableName);
                controller.setColumnList(FXCollections.observableList(tableColumns));
                controller.setTableName(tableName);
            }
            controller.showDialogStage();
        } catch (Exception e) {
            _LOG.error(e.getMessage(), e);
            AlertUtil.showErrorAlert(e.getMessage());
        }
    }
    
    @FXML
    public void openTableColumnCustomizationMapper() {
        if (tableName == null) {
            AlertUtil.showWarnAlert("请先在左侧选择数据库表");
            return;
        }
        SelectTableColumn4MapperController controller = (SelectTableColumn4MapperController) loadFXMLPage("定制列", FXMLPage.SELECT_TABLE_COLUMN_4_MAPPER, true);
        controller.setMainUIController(this);
        try {
            if (!tableName.equals(controller.getTableName())) {
                List<UITableColumnVO> tableColumns = DbUtil.getTableColumns(selectedDatabaseConfig, tableName);
                
                //过滤公共属性
                tableColumns = filterCommonProps2(tableColumns, Boolean.TRUE);
                
                controller.setColumnList(FXCollections.observableList(tableColumns));
                controller.setTableName(tableName);
            }
            controller.showDialogStage();
        } catch (Exception e) {
            _LOG.error(e.getMessage(), e);
            AlertUtil.showErrorAlert(e.getMessage());
        }
    }
    
    private static final List<String> defaultCommProps = new ArrayList<>(
    		Arrays.asList("IS_DELETE", "CREATE_AT", "CREATE_BY", "UPDATE_AT", "UPDATE_BY"));
    private List<UITableColumnVO> filterCommonProps2(List<UITableColumnVO> colums, Boolean true1) {
    	List<UITableColumnVO> columsList = new ArrayList<>();
    	if(CollectionUtils.isEmpty(colums)) { return columsList; }
    	
    	columsList = colums.stream().filter(item -> !defaultCommProps.contains(item.getColumnName().toUpperCase()))
    			.collect(Collectors.toList());
    	
    	return columsList;
	}

	/**
     * 检查并创建不存在的文件夹
     *
     * @return
     */
    private boolean checkDirs(GeneratorConfig config) {
    	config.setDomTargetProject(FilenameUtils.normalize(config.getProjectFolder().concat("/").concat(config.getDomTargetProject())));
    	config.setProviderTargetProject(FilenameUtils.normalize(config.getProjectFolder().concat("/").concat(config.getProviderTargetProject())));
		config.setMapperTargetProject(FilenameUtils.normalize(config.getProjectFolder().concat("/").concat(config.getMapperTargetProject())));
		config.setDtoTargetProject(FilenameUtils.normalize(config.getProjectFolder().concat("/").concat(config.getDtoTargetProject())));
		
		config.setConverterTargetProject(FilenameUtils.normalize(config.getProjectFolder().concat("/").concat(config.getConverterTargetProject())));
		config.setServiceTargetProject(FilenameUtils.normalize(config.getProjectFolder().concat("/").concat(config.getServiceTargetProject())));
		config.setServiceImplTargetProject(FilenameUtils.normalize(config.getProjectFolder().concat("/").concat(config.getServiceImplTargetProject())));
		config.setRequestSaveTargetProject(FilenameUtils.normalize(config.getProjectFolder().concat("/").concat(config.getRequestSaveTargetProject())));
		
		config.setRequestUpdateTargetProject(FilenameUtils.normalize(config.getProjectFolder().concat("/").concat(config.getRequestUpdateTargetProject())));
		config.setResponseTargetProject(FilenameUtils.normalize(config.getProjectFolder().concat("/").concat(config.getResponseTargetProject())));
		config.setExceptionTargetProject(FilenameUtils.normalize(config.getProjectFolder().concat("/").concat(config.getExceptionTargetProject())));
		config.setControllerTargetProject(FilenameUtils.normalize(config.getProjectFolder().concat("/").concat(config.getControllerTargetProject())));

		List<String> dirs = new ArrayList<>();
		dirs.add(config.getProjectFolder());
		
		dirs.add(config.getDomTargetProject());
		dirs.add(config.getProviderTargetProject());
		dirs.add(config.getMapperTargetProject());
		dirs.add(config.getDtoTargetProject());
		
		dirs.add(config.getConverterTargetProject());
		dirs.add(config.getServiceTargetProject());
		dirs.add(config.getServiceImplTargetProject());
		dirs.add(config.getRequestSaveTargetProject());

		dirs.add(config.getRequestUpdateTargetProject());
		dirs.add(config.getResponseTargetProject());
		dirs.add(config.getExceptionTargetProject());
		dirs.add(config.getControllerTargetProject());
		
		boolean haveNotExistFolder = false;
		for (String dir : dirs) {
			File file = new File(dir);
			if (!file.exists()) {
				haveNotExistFolder = true;
			}
		}
		if (haveNotExistFolder) {
			Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
			alert.setContentText(FOLDER_NO_EXIST);
			Optional<ButtonType> optional = alert.showAndWait();
			if (optional.isPresent()) {
				if (ButtonType.OK == optional.get()) {
					try {
						for (String dir : dirs) {
							FileUtils.forceMkdir(new File(dir));
						}
						return true;
					} catch (Exception e) {
						AlertUtil.showErrorAlert("创建目录失败，请检查目录是否是文件而非目录");
					}
				} else {
					return false;
				}
			}
		}
        return true;
    }

    @FXML
    public void openTargetFolder() {
        GeneratorConfig generatorConfig = getGeneratorConfigFromUI();
        String projectFolder = generatorConfig.getProjectFolder();
        try {
            Desktop.getDesktop().browse(new File(projectFolder).toURI());
        }catch (Exception e) {
            AlertUtil.showErrorAlert("打开目录失败，请检查目录是否填写正确" + e.getMessage());
        }

    }


    public List<ColumnEntity> getCeEqualList() {
		return ceEqualList;
	}

	public List<ColumnEntity> getCeInList() {
		return ceInList;
	}

	public List<ColumnEntity> getCeLikeList() {
		return ceLikeList;
	}

	public void setCeEqualList(List<ColumnEntity> ceEqualList) {
		this.ceEqualList = ceEqualList;
	}

	public void setCeInList(List<ColumnEntity> ceInList) {
		this.ceInList = ceInList;
	}

	public void setCeLikeList(List<ColumnEntity> ceLikeList) {
		this.ceLikeList = ceLikeList;
	}
	
    public List<ColumnEntity> getCeAllList() {
		return ceAllList;
	}

	public void setCeAllList(List<ColumnEntity> ceAllList) {
		this.ceAllList = ceAllList;
	}
}
